package org.texteasy.sms;

import java.util.HashMap;

import org.texteasy.BulkMessenger;
import org.texteasy.R;
import org.texteasy.TextEasyApp;
import org.texteasy.sms.SMSConstants.MMS;
import org.texteasy.sms.SMSConstants.SMS;

import android.app.Activity;
import android.app.ListActivity;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.telephony.TelephonyManager;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.LineHeightSpan;
import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.FilterQueryProvider;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;

public class SMSThreadList extends ListActivity {

	public static final String EXTRA_THREAD_ID = "THREAD_ID";
	
	
	
	/**
     * The column to distinguish SMS &amp; MMS messages in query results. If
     * the type is MMS the value will be "mms"
     */
    public static final String TYPE_DISCRIMINATOR_COLUMN =
            "transport_type";
	
    private final static int COLUMN_TYPE_DISCRIMINATOR = 0;
    private final static int COLUMN_ID = 1;
    private final static int COLUMN_SMS_ADDRESS = 2;
    private final static int COLUMN_SMS_BODY = 3;
    private final static int COLUMN_SMS_DATE = 4;
    private final static int COLUMN_SMS_TYPE = 5;
    private final static int COLUMN_MMS_SUBJECT = 6;
    private final static int COLUMN_MMS_DATE = 8;
    
    
	public static final String[] PROJECTION = new String[]{
		TYPE_DISCRIMINATOR_COLUMN,
		BaseColumns._ID,
		SMS.ADDRESS,
		SMS.BODY,
		SMS.DATE,
		SMS.TYPE/*,
		
		MMS.SUBJECT,
		MMS.SUBJECT_CHARSET,
		MMS.DATE*/
	};
	
	private long threadId;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.sms_thread_list);
		
		ListView listView = getListView();
		listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
		listView.setTextFilterEnabled(true);
		
		if(!getIntent().getExtras().containsKey(EXTRA_THREAD_ID)){
			throw new IllegalArgumentException("SMSThreadList requires a ThreadId");
		}
		
		this.threadId = (Long)getIntent().getExtras().get(EXTRA_THREAD_ID);
		
		//filter out any mms messages. They are not supported at this time.
		Cursor cursor = getContentResolver().query(
				ContentUris.withAppendedId(SMSConstants.CONTENT_URI, threadId),
				PROJECTION, TYPE_DISCRIMINATOR_COLUMN + "!= '" + SMSConstants.MMS_TYPE + 
				"' AND " + SMS.BODY + " like '%'", null, null);
		
		setListAdapter(new SMSThreadListAdapter(this, R.layout.sms_thread_row, cursor, 
				this.threadId));
		
		//ContentUris.withAppendedId(Threads.CONTENT_URI, mThreadId)
	}
	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		
		Cursor cursor = (Cursor) getListView().getItemAtPosition(position);
		
		String messageType = cursor.getString(COLUMN_TYPE_DISCRIMINATOR);
		
		Intent toReturn = new Intent();
		if(SMSConstants.MMS_TYPE.equalsIgnoreCase(messageType)){
			//TODO: this almost certainly isn't right.
			toReturn.putExtra(BulkMessenger.EXTRA_SMS_BODY, cursor.getString(COLUMN_MMS_SUBJECT));
		}else{
			toReturn.putExtra(BulkMessenger.EXTRA_SMS_BODY, cursor.getString(COLUMN_SMS_BODY));
		}
		setResult(RESULT_OK, toReturn);
		finish();
	}
	
	final static class SMSThreadItemCache {
		public TextView messageView;
		public ImageView avatarView;
	}
	
	private static final class SMSThreadListAdapter extends ResourceCursorAdapter {
		
		private final String meString; 
		private final String meAddress;
		private final RecipientCache recipientCache;
		private final HashMap<String, Contact> addressToContactMap = new HashMap<String, Contact>();
		private final TextAppearanceSpan textSmallSpan;
		private final ForegroundColorSpan colorSpan;
		private final int dateFormatFlags;
		private final Drawable sDefaultContactImage;
		private LineHeightSpan span = new LineHeightSpan() {
	        public void chooseHeight(CharSequence text, int start,
	                int end, int spanstartv, int v, FontMetricsInt fm) {
	            fm.ascent -= 10;
	        }
	    };
		
		public SMSThreadListAdapter(final Context context,final int resource,
				final Cursor cursor, final long threadId) {
			super(context, resource, cursor);
			
			meString = context.getString(R.string.threadlist_sender_self);
			
			Activity parentActivity = (Activity)context;
			TextEasyApp application = (TextEasyApp)parentActivity.getApplication();
			recipientCache = application.getRecipientCache();
			textSmallSpan = new TextAppearanceSpan(context, android.R.style.TextAppearance_Small);
			
			int color = context.getResources().getColor(R.color.timestamp_color);
			colorSpan = new ForegroundColorSpan(color);
			
			dateFormatFlags = DateUtils.FORMAT_NO_NOON_MIDNIGHT |
	        	DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_CAP_AMPM |
	        	DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE;
			
			setFilterQueryProvider(new FilterQueryProvider(){
				@Override
				public Cursor runQuery(CharSequence constraint) {
					
					String filter = "%";
					if(constraint != null && !"".equals(constraint.toString().trim())){
						filter = "%" + constraint + "%";
					}
					
					Cursor cursor = context.getContentResolver().query(
							ContentUris.withAppendedId(SMSConstants.CONTENT_URI, threadId),
							PROJECTION, TYPE_DISCRIMINATOR_COLUMN + "!= '" + SMSConstants.MMS_TYPE + 
							"' AND " + SMS.BODY + " like '" + filter + "'", null, null);
					return cursor;
				}
			});
			
			sDefaultContactImage = context.getResources().getDrawable(R.drawable.ic_contact_picture);
			TelephonyManager telephonyManager = (TelephonyManager)context.getApplicationContext()
	         	.getSystemService(Context.TELEPHONY_SERVICE);
			meAddress = telephonyManager.getLine1Number();
		}
		
		@Override
		public View newView(final Context context,final  Cursor cursor,final ViewGroup parent) {
			final View view = super.newView(context, cursor, parent);
			
			final SMSThreadItemCache cache = new SMSThreadItemCache();
			cache.messageView = (TextView)view.findViewById(R.id.sms_message);
			cache.avatarView = (ImageView)view.findViewById(R.id.avatar);
			view.setTag(cache);
			return view;
		}
		
		@Override
		public void bindView(final View view,final Context context,final Cursor cursor) {
			
			final SMSThreadItemCache cache = (SMSThreadItemCache) view.getTag();
			
			String messageType = cursor.getString(COLUMN_TYPE_DISCRIMINATOR);
			CharSequence body = null;
			if(SMSConstants.MMS_TYPE.equalsIgnoreCase(messageType)){
				body = cursor.getString(COLUMN_MMS_SUBJECT);
			}else{
				
				int smsBox = cursor.getInt(COLUMN_SMS_TYPE);
				
				Contact contact = null;
				String displayName = null;
				if(SMS.isOutgoingFolder(smsBox)){
					//outgoing message
					displayName = meString;
					contact = addressToContactMap.get(meAddress);
					if(contact == null){
						//the lookup is somewhat expensive so cache the result
						contact = recipientCache.getContactByAddress(meAddress);
						if(contact == null){
							contact = new Contact();
							contact.setDisplayValue(meAddress);
						}
						addressToContactMap.put(meAddress, contact);
					}
				}else{
					//incoming message
					//lookup display name via address
					String address = cursor.getString(COLUMN_SMS_ADDRESS);
					
					contact = addressToContactMap.get(address);
					if(contact == null){
						//the lookup is somewhat expensive so cache the result
						contact = recipientCache.getContactByAddress(address);
						if(contact == null){
							contact = new Contact();
							contact.setDisplayValue(address);
						}
						addressToContactMap.put(address, contact);
					}
					displayName = contact.getDisplayValue();
				}
				
				long date = cursor.getLong(COLUMN_SMS_DATE);
				
				String dateString = DateUtils.formatDateTime(context, 
						date, dateFormatFlags);
				
				body = formatMessage(context, displayName, cursor.getString(COLUMN_SMS_BODY), 
						null, dateString);
				
				if(contact != null && contact.getAvatar() != null){
					cache.avatarView.setImageDrawable(contact.getAvatar());
				}else{
					cache.avatarView.setImageDrawable(sDefaultContactImage);
				}
			}
			
			cache.messageView.setText(body);
		}
		
		private CharSequence formatMessage(Context context, String contact, String body,
                String subject, String timestamp) {
			
			CharSequence template = context.getResources().getText(R.string.name_colon);
			
			SpannableStringBuilder buf =
	            new SpannableStringBuilder(TextUtils.replace(template,
	                new String[] { "%s" },
	                new CharSequence[] { contact }));
			
			boolean hasSubject = !TextUtils.isEmpty(subject);
	        if (hasSubject) {
	            buf.append(context.getResources().getString(R.string.inline_subject, subject));
	        }

	        if (!TextUtils.isEmpty(body)) {
	            // Converts html to spannable if ContentType is "text/html".
                if (hasSubject) {
                    buf.append(" - ");
                }
                buf.append(body);
	        }
	        
	     // We always show two lines because the optional icon bottoms are aligned with the
	        // bottom of the text field, assuming there are two lines for the message and the sent time.
	        buf.append("\n");
	        int startOffset = buf.length();

	        startOffset = buf.length();
	        buf.append(TextUtils.isEmpty(timestamp) ? " " : timestamp);

	        buf.setSpan(textSmallSpan, startOffset, buf.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
	        buf.setSpan(span, startOffset+1, buf.length(), 0);

	        // Make the timestamp text not as dark
	        buf.setSpan(colorSpan, startOffset, buf.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

	        //buf.setSpan(mLeadingMarginSpan, 0, buf.length(), 0);
	        return buf;
		}
	

		
	}
	
}
